package com.cloudwebrtc.service;

import java.text.DecimalFormat;
import java.util.Timer;
import java.util.TimerTask;

import org.webrtc.MediaCodecVideoDecoder;
import org.webrtc.MediaCodecVideoEncoder;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import android.widget.RemoteViews;

import com.cloudwebrtc.LogcatHelper;
import com.cloudwebrtc.preference.SettingSharedPreference;
import com.cloudwebrtc.receiver.HeadsetPlugReceiver;
import com.cloudwebrtc.util.Contacts;
import com.cloudwebrtc.util.Debug;
import com.cloudwebrtc.util.UIUtils;
import com.cloudwebrtc.voip.mediaengine.CallStatistics;
import com.cloudwebrtc.voip.mediaengine.RTCVoiceEngine;
import com.cloudwebrtc.voip.mediaengine.StreamType;
import com.cloudwebrtc.voip.mediaengine.VideoFrameInfo;
import com.cloudwebrtc.voip.mediaengine.VideoStreamObserver;
import com.cloudwebrtc.voip.sipenginev2.Call;
import com.cloudwebrtc.voip.sipenginev2.CallReport;
import com.cloudwebrtc.voip.sipenginev2.CallReportStatus;
import com.cloudwebrtc.voip.sipenginev2.CallState;
import com.cloudwebrtc.voip.sipenginev2.CallStateEventListener;
import com.cloudwebrtc.voip.sipenginev2.Config;
import com.cloudwebrtc.voip.sipenginev2.Direction;
import com.cloudwebrtc.voip.sipenginev2.DtmfMethod;
import com.cloudwebrtc.voip.sipenginev2.LogLevel;
import com.cloudwebrtc.voip.sipenginev2.RegistrationErrorCode;
import com.cloudwebrtc.voip.sipenginev2.RegistrationEventListener;
import com.cloudwebrtc.voip.sipenginev2.RegistrationState;
import com.cloudwebrtc.voip.sipenginev2.SipEngine;
import com.cloudwebrtc.voip.sipenginev2.SipEngineFactory;
import com.cloudwebrtc.voip.sipenginev2.SipProfile;
import com.cloudwebrtc.voip.sipenginev2.SipTransportType;
import com.cloudwebrtc.voip.sipenginev2.impl.CallImpl;
import com.wireless.serialservice.SerialService;
import com.wireless.sipsdk.SipAddStreamListener;
import com.wireless.sipsdk.SipCallDisConnectListener;
import com.wireless.sipsdk.SipCallListener;
import com.wireless.sipsdk.SipReceivedListener;
import com.wireless.sipsdk.SipRegisterListener;
import com.wireless.sipsdk.SipapCallPeer;

public class PhoneService extends Service implements RegistrationEventListener,
		CallStateEventListener , VideoStreamObserver {
	private final String TAG = PhoneService.class.getSimpleName();
	private static PhoneService the_service_instance_ = null;
	private MediaPlayer mediaPlayer;
	// 震动
	private Vibrator vib;
	private Call current_call = null;
	private static SipEngine the_sipengine_ = null;
	private int _maxVolume = 0; // Android max level (commonly 5)
	private int _volumeLevel = 200;
	private boolean send_video = true;
	private static SipProfile profile = null;
	private HeadsetPlugReceiver headsetPlugReceiver;
	private boolean headset_is_plugin_ = false;
	private String phoneNumber, password, sip_server;
	public Handler mHandler = new Handler();
	Timer mTimer = new Timer("SipEngine scheduler");
	
    private String local_device_type = "doorbell";
    private String remote_device_type;
	private SipRegisterListener mSipRiListener;
	private SipCallListener mSipCaListener;
	private SipReceivedListener mSipReListener;
	private SipAddStreamListener mSipAsListener;
    private SipCallDisConnectListener mSipCallDisconnectListener;
	
	public void setSipRiListener(SipRegisterListener mListener) {
		this.mSipRiListener = mListener;
	}
	
	public void setSipCaListener(SipCallListener mListener) {
		this.mSipCaListener = mListener;
	}
	public void setAddStreamListener(SipAddStreamListener mListener) {
		this.mSipAsListener = mListener;
	}
	
	public void setSipReListener(SipReceivedListener mListener) {
		this.mSipReListener = mListener;
	}
	
	 public void setSipCaDisListener(SipCallDisConnectListener mListener) {
         mSipCallDisconnectListener = mListener;
     }

	//end by xuweihong
	
	public static boolean isready() {
		return (the_service_instance_ != null);
	}

	static public SipEngine getSipEngine() {
		return the_sipengine_;
	}

	
	public static PhoneService instance() {
		if (the_service_instance_ == null) {
			throw new RuntimeException(
					"the_service_instance_ not instanciated yet");
		} else {
			return the_service_instance_;
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	public boolean MakeCall(String number, boolean video_call) {
		if (current_call != null || profile == null) {
			/* busy */
			return false;
		}
		current_call = the_sipengine_.GetCallManager().MakeCall(profile,
				number, true, video_call, false);
		return true;
	}
	
	public boolean MakeCall(String number, boolean video_call, String device_type) {
		if (current_call != null || profile == null) {
			/* busy */
			return false;
		}
		local_device_type = device_type;
		current_call = the_sipengine_.GetCallManager().MakeCall(profile,
				number, device_type, true, video_call, false);
		return true;
	}

	public boolean Hangup()
	{
		return the_sipengine_.GetCallManager().HangupAllCalls();
	}

	public boolean MuteMic(boolean yesno)
	{
		if(InCalling())
		{
			current_call.GetMediaStream().GetAudioStream().MuteMic(yesno);
		}
		return false;
	}

	public boolean HoldCall(boolean yesno) {
		return false;
	}
	
	public void SetHeadsetIsPlug(boolean yesno)
	{
		headset_is_plugin_ = yesno;
	}

	public boolean SetLoudspeakerStatus(boolean yesno) {
		boolean speaker_on = yesno;
		if(headset_is_plugin_){
			speaker_on = false;
		}
		the_sipengine_.GetMediaEngine().GetVoiceEngine().SetLoudspeakerStatus(speaker_on);
		if(audioManager == null)
			audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
		audioManager.setSpeakerphoneOn(speaker_on);
		return true;
	}

	public boolean UpdateCall(boolean video_mode) {
		return false;
	}

	public boolean AcceptCall() {
		if(current_call!=null)
		{
			current_call.Accept();
			return true;
		}
		return false;
	}
	
	public boolean AcceptCall(boolean send_video) {
		this.send_video = send_video;
		if(current_call!=null)
		{
			current_call.Accept(true, send_video);
			return true;
		}
		return false;
	}

	public boolean MakeUrlCall(String url, boolean video_mode) {
		return false;
	}

	public boolean SendDtmf(String tone)
	{
		if(InCalling())
		{
			current_call.SendDtmf(DtmfMethod.INFO, tone,false);
			return true;
		}
		return false;
	}
	
	public boolean InCalling() {
		return (current_call != null && current_call.GetCallState().IntgerValue() == CallState.Answered.IntgerValue());
	}
	
	public boolean getCallIncoming() {
		return (current_call != null && current_call.GetDirection().IntgerValue() == Direction.Incoming.IntgerValue());
	}
	
	public boolean InVideoCalling() {
		return (current_call!=null && current_call.GetCallState().IntgerValue() == CallState.Answered.IntgerValue() && current_call.GetSupportVideo());
	}

	public String SendTextMessage(String peer, String message) {
		return null;
	}
	
	public boolean StartVideoChannel() {
		if(InCalling())
		{
			//System.out.println("==================StartVideoChannel=================1");
			/*if(this.getCallIncoming()) {
				//Toast.makeText(this, "StartVideoChannel====1", Toast.LENGTH_LONG).show();
			    if(local_device_type.equals("doorbell") && remote_device_type.equals("phone"))
			    {
			    	System.out.println("==================StartVideoChannel=================2");
			    	//Toast.makeText(this, "StartVideoChannel====phone", Toast.LENGTH_LONG).show();
			    	current_call.GetMediaStream().GetVideoStream().StartSending();
			    	current_call.GetMediaStream().GetVideoStream().StopReceiving();
			    	
			    } else if(local_device_type.equals("phone")  && remote_device_type.equals("phone"))
			    {
			    	System.out.println("==================StartVideoChannel=================3");
			    	current_call.GetMediaStream().GetVideoStream().StartSending();
					current_call.GetMediaStream().GetVideoStream().StartReceiving();
					
			    } else if(local_device_type.equals("phone") && remote_device_type.equals("doorbell"))
			    {
			    	System.out.println("==================StartVideoChannel=================4");
			    	current_call.GetMediaStream().GetVideoStream().StartReceiving();
			    	current_call.GetMediaStream().GetVideoStream().StopSending();
			    }
			}
			else {*/
				//System.out.println("==================StartVideoChannel=================5");
				current_call.GetMediaStream().GetVideoStream().StartSending();
				current_call.GetMediaStream().GetVideoStream().StartReceiving();
			//}	
			return true;
		}
		return false;
	}

	public boolean StopVideoChannel() {
		if(InCalling())
		{
			current_call.GetMediaStream().GetVideoStream().StopReceiving();
			current_call.GetMediaStream().GetVideoStream().StopSending();
			return true;
		}
		return false;
	}

	public boolean SetupVideoStream(int camera_index,int rotation_new, long local_window_id, long remote_window_id) 
	{
		if(current_call != null)
		{
			SharedPreferences sp = PreferenceManager
					.getDefaultSharedPreferences(this);
			String video_size = "qvga";//sp.getString("sip_account_video_size", "qvga");
			
			int width = 320;
			int height = 240;
			int bitrate = 256;
			int fps = 12;
			
			if(video_size.equals("qvga"))
			{
				width = 320;
				height = 240;
				bitrate = 256;
				fps = 12;
			} else if (video_size.equals("cif"))
			{
				width = 352;
				height = 352;
				bitrate = 384;
				fps = 15;
			} else if (video_size.equals("vga"))
			{
				width = 640;
				height = 480;
				bitrate = 512;
				fps = 15;
			} else if(video_size.equals("hd"))
			{
				width = 1280;
				height = 720;
				bitrate = 1024;
				fps = 15;
			}
			
			current_call.GetMediaStream().GetVideoStream().SetupVideoStream(
					camera_index, 
					local_window_id,
					remote_window_id,
					rotation_new,
					width,
					height, 
					bitrate, 
					fps);
	
			return true;
		}
		return false;
	}


	public boolean SetCameraOutputRotation(int rotation) {
		if(InCalling())
		{
			current_call.GetMediaStream().GetVideoStream().ChangeCaptureRotation(rotation);
			return true;
		}
		return false;
	}

	public boolean SwapCamera(int camera_index,int rotation_new, Object local_window_id) {
		if(InCalling())
		{
			current_call.GetMediaStream().GetVideoStream().ChangeCamera(camera_index, rotation_new, local_window_id);
			return true;
		}
		return false;
	}

	public int GetCameraOrientation(int cam_index) {
		return the_sipengine_.GetMediaEngine().GetVideoEngine().GetCameraOrientation(cam_index);
	}
	
	public CallStatistics GetAudioCallStatistics()
	{
		if(InCalling())
		{
			return current_call.GetMediaStream().GetAudioStream().GetCallStatistics();
		}
		
		return new CallStatistics();
	}
	
	public CallStatistics GetVideoCallStatistics()
	{
		if(InCalling() && current_call.GetSupportVideo())
		{
			return current_call.GetMediaStream().GetVideoStream().GetCallStatistics();
		}
		
		return new CallStatistics();
	}
	
	public void ResetVideoChannel()
	{
		StopVideoChannel();
		StartVideoChannel();
	}
	
	public boolean ProfileIsRegistered()
	{
		if(the_sipengine_ == null || profile == null)
			return false;
		
		return the_sipengine_.GetRegistrationManager().ProfileIsRegistered(profile);
	}
	
	private static RegistrationState reg_state = RegistrationState.None;
	public RegistrationState LastRegistrationState()
	{
		return reg_state;
	}
	private static RegistrationErrorCode reg_error_code = RegistrationErrorCode.None;
	public RegistrationErrorCode LastRegistrationErrorCode()
	{
		return reg_error_code;
	}
	
	private void unregisterHeadsetReceiver(){  
	    this.unregisterReceiver(headsetPlugReceiver);  
	}  
	
	private void registerHeadsetPlugReceiver(){  
        headsetPlugReceiver  = new HeadsetPlugReceiver ();  
        IntentFilter  filter = new IntentFilter();  
        filter.addAction("android.intent.action.HEADSET_PLUG");  
        registerReceiver(headsetPlugReceiver, filter);  
    }  

	@Override
	public void onCreate() {
		super.onCreate();
		Debug.e(TAG, "PhoneService::onCreate");
		
		if(MediaCodecVideoEncoder.isH264HwSupported())
		{
			Debug.e(TAG, "isH264Hw Encoder Supported");
		}
		if(MediaCodecVideoEncoder.isVp8HwSupported())
		{
			Debug.e(TAG, "isVp8Hw Encoder Supported");
		}
		
		if(MediaCodecVideoDecoder.isH264HwSupported())
		{
			Debug.e(TAG, "isH264Hw Decoder Supported");
		}
		
		if(MediaCodecVideoDecoder.isVp8HwSupported())
		{
			Debug.e(TAG, "isH264Hw Decoder Supported");
		}
		
		/*导入LogCat 捕获类*/
		LogcatHelper.getInstance(this).start(); 
		 
		the_service_instance_ = this;
		
		if (the_sipengine_ == null)
		{
			the_sipengine_ = SipEngineFactory.instance().CreateSipEngine(this);
			
			the_sipengine_.Initialize();

			Debug.d("*SipEngine*", "Start CoreEventProgress timer");

			TimerTask lTask = new TimerTask() {
				@Override
				public void run() {
					the_sipengine_.RunEventLoop();
				}
			};
			mTimer.scheduleAtFixedRate(lTask, 0, 100);
		}

		/* 初始设置假设网络不可用 */
		the_sipengine_.GetRegistrationManager().SetNetworkReachable(false);
		the_sipengine_.GetCallManager().SetMaxConcurrentCall(1);
		mNetWorkBroadCast = new NetWorkBroadCast();
		IntentFilter filter = new IntentFilter();
		filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
		registerReceiver(mNetWorkBroadCast, filter);

		the_sipengine_.GetCallManager().RegisterCallStateObserver(this);
		the_sipengine_.GetRegistrationManager().RegisterRegistrationObserver(
				this);
		
		AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

		_maxVolume = am.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL);
		if (_maxVolume <= 0) {
			Debug.i(TAG, "Could not get max volume!");
		} else {
			int androidVolumeLevel = (_volumeLevel * _maxVolume) / 255;
			_volumeLevel = (androidVolumeLevel * 255) / _maxVolume;
			am.setStreamVolume(AudioManager.STREAM_VOICE_CALL, _maxVolume, 0);
		}
		
		registerHeadsetPlugReceiver();
		
		loadConfig();
	}

	private NetWorkBroadCast mNetWorkBroadCast;

	public static void startService(Context ctx)
    {
		Debug.i("PhoneService", "Need start service ="
				+ (the_service_instance_ == null));
		Intent intent = new Intent(ctx, PhoneService.class);
		ctx.startService(intent);
	}
	
	public boolean isTvBoxMode()
	{
		SharedPreferences sp = PreferenceManager
				.getDefaultSharedPreferences(this);
		
		return sp.getBoolean("tvbox_mode", false);
	}
	
	public void loadConfig()
	{
		SharedPreferences sp = PreferenceManager
				.getDefaultSharedPreferences(this);
		
		Config cfg = the_sipengine_.GetDefaultConfig();
		cfg.user_agent = "Android Client 1.0 ("
				+ android.os.Build.MANUFACTURER + ")";
		/*boolean use_webrtc_mode = true;//sp.getBoolean("sip_account_use_webrtc_mode", true);
		String stun_server = sp.getString("sip_account_stun_server", "");
		String turn_server = sp.getString("sip_account_turn_server", "");
		boolean use_turn_mode = sp.getBoolean("sip_account_use_turn_mode", true);
		String turn_user = sp.getString("sip_account_turn_user", "");
		String turn_password = sp.getString("sip_account_turn_password", "");*/
		
		/*载入全局配置*/
		
		cfg.log_on = true;
		cfg.log_level = LogLevel.Stack;
		
		//if(!TextUtils.isEmpty(stun_server))
		//{
			//String[] vec = stun_server.split(":");
			//cfg.stun_server = vec[0];
			//cfg.stun_server_port= (vec.length > 1)? Integer.parseInt(vec[1]) : 19302;
		//} else
		//{
			cfg.stun_server = "101.200.187.190";
			cfg.stun_server_port = 19302;
		//}

		//if(!TextUtils.isEmpty(turn_server))
		//{
			//String[] vec = turn_server.split(":");
			//cfg.turn_server = vec[0];
			//cfg.turn_server_port = (vec.length > 1)? Integer.parseInt(vec[1]) : 19302;
		//} else
		//{
			cfg.turn_server = "101.200.187.190";
			cfg.turn_server_port = 19302;
		//}

		//if(!TextUtils.isEmpty(turn_user))
		//{
			//cfg.turn_username = turn_user;
		//}else
		//{
			cfg.turn_username = "700";
		//}
		
		//if(!TextUtils.isEmpty(turn_password))
		//{
			//cfg.turn_password = turn_password;
		//} else
		//{
			cfg.turn_password = "700";
		//}
		
		//if(!use_turn_mode)
		//{
		//	cfg.turn_server = "";
			//cfg.turn_username = "";
			//cfg.turn_password = "";
		//}
		
		cfg.rtp_port_start = 30000;
		cfg.rtp_port_end = 65535;
		
		/*
		 * "audio_codecs_isac"
		 * "audio_codecs_g722" 
		 * "audio_codecs_g729"
		 * "audio_codecs_gsm" 
		 * "audio_codecs_libc" 
		 * "audio_codecs_pcma"
		 * "audio_codecs_pcmu"
		 */
		
		 //Set Audio Codecs
	    {
	        String audio_codecs = "";
	        boolean audio_codecs_isac = false;//sp.getBoolean("audio_codecs_isac", true);
	        if(audio_codecs_isac)
	        {
	            audio_codecs += "isac";
	        }
	        boolean audio_codecs_opus = false;//sp.getBoolean("audio_codecs_opus", true);
	        if(audio_codecs_opus)
	        {
	            if(audio_codecs.length() > 0 )
	                audio_codecs += ",";
	            audio_codecs += "opus";
	        }
	        boolean audio_codecs_g722 = false;//sp.getBoolean("audio_codecs_g722", true);
	        if(audio_codecs_g722)
	        {
	            if(audio_codecs.length() > 0 )
	                audio_codecs += ",";
	            audio_codecs += "g722";
	        }
	        boolean audio_codecs_g729 = false;//sp.getBoolean("audio_codecs_g729", true);
	        if(audio_codecs_g729)
	        {
	            if(audio_codecs.length() > 0 )
	                audio_codecs += ",";
	            audio_codecs += "g729";
	        }
	        boolean audio_codecs_gsm = false;// sp.getBoolean("audio_codecs_gsm", true);
	        if(audio_codecs_gsm)
	        {
	            if(audio_codecs.length() > 0 )
	                audio_codecs += ",";
	            audio_codecs += "GSM";
	        }
	        boolean audio_codecs_ilbc = false;//sp.getBoolean("audio_codecs_ilbc", true);
	        if(audio_codecs_ilbc)
	        {
	            if(audio_codecs.length() > 0 )
	                audio_codecs += ",";
	            audio_codecs += "ILBC";
	        }
	        boolean audio_codecs_pcmu = false;//sp.getBoolean("audio_codecs_pcmu", true);
	        if(audio_codecs_pcmu)
	        {
	            if(audio_codecs.length() > 0 )
	                audio_codecs += ",";
	            audio_codecs += "PCMU";
	        }
	        boolean audio_codecs_pcma = true;//sp.getBoolean("audio_codecs_pcma", true);
	        if(audio_codecs_pcma)
	        {
	            if(audio_codecs.length() > 0 )
	                audio_codecs += ",";
	            audio_codecs += "PCMA";
	        }
	        
	        Debug.d(TAG, "Set Audio Codecs : " + audio_codecs);
	        
	        cfg.audio_codecs = audio_codecs;
	    }
		//cfg.audio_codecs = "ISAC,G729,GSM,PCMA,PCMU";
		
		/*
		 * "video_codecs_vp8"
		 * "video_codecs_vp9" 
		 * "video_codecs_h264"
		 * "video_codecs_red" 
		 * "video_codecs_ulpfec" 
		 * "video_codecs_rtx"
		 */
	    
	  //Set Video Codecs
	    {
	        String video_codecs = "";
	        boolean video_codecs_vp8 = true;//sp.getBoolean("video_codecs_vp8", true );
	        if(video_codecs_vp8)
	        {
	            video_codecs += "VP8";
	        }
	        boolean video_codecs_vp9 = true;//sp.getBoolean("video_codecs_vp9", true );
	        if(video_codecs_vp9)
	        {
	            if(video_codecs.length() > 0 )
	                video_codecs += ",";
	            video_codecs += "VP9";
	        }
	        boolean video_codecs_h264 = true;//sp.getBoolean("video_codecs_h264", true );
	        if(video_codecs_h264)
	        {
	            if(video_codecs.length() > 0 )
	                video_codecs += ",";
	            video_codecs += "H264";
	        }
	        boolean video_codecs_red = true;//sp.getBoolean("video_codecs_red", true );
	        if(video_codecs_red)
	        {
	            if(video_codecs.length() > 0 )
	                video_codecs += ",";
	            video_codecs += "red";
	        }
	        boolean video_codecs_ulpfec = true;//sp.getBoolean("video_codecs_ulpfec", true );
	        if(video_codecs_ulpfec)
	        {
	            if(video_codecs.length() > 0 )
	                video_codecs += ",";
	            video_codecs += "ulpfec";
	        }
	        boolean video_codecs_rtx = true;//sp.getBoolean("video_codecs_rtx", true );
	        if(video_codecs_rtx)
	        {
	            if(video_codecs.length() > 0 )
	                video_codecs += ",";
	            video_codecs += "rtx";
	        }
	        
	        Debug.d(TAG,"Set Video Codecs : " + video_codecs);
	        
	        cfg.video_codecs = video_codecs;
	    }

		
		//cfg.audio_codecs = "VP8,VP9,red,uplfec,rtx";
		
		// cfg.udp_port = 0;
		// cfg.tcp_port = 35070;
		// cfg.tls_port = 0;
	    cfg.Save();
	    
	    RTCVoiceEngine voice_engine = the_sipengine_.GetMediaEngine()
				.GetVoiceEngine();
		
	    boolean audio_aecm = true;//sp.getBoolean("audio_aecm", true);
	    boolean audio_aec = false;//sp.getBoolean("audio_aec", false);
	    voice_engine.SetAECMode((audio_aecm || audio_aec )? 1 : 0, audio_aec? RTCVoiceEngine.kEcAec : RTCVoiceEngine.kEcAecm);
	    boolean audio_agc = true;//sp.getBoolean("audio_agc", true);
	    voice_engine.SetAGCMode(audio_agc? 1 : 0, RTCVoiceEngine.kAgcDefault);
	    boolean audio_ns = true;//sp.getBoolean("audio_ns", true);
	    voice_engine.SetNSMode(audio_ns? 1 : 0, RTCVoiceEngine.kNsVeryHighSuppression);
	}
	
	public void refreshRegistration()
	{
		if (the_sipengine_ != null && profile != null)
		{
			if(ProfileIsRegistered())
				the_sipengine_.GetRegistrationManager().RefreshRegistration(profile);
			else
			{
				registerSipAccount();
			}
		
		}
	}

	/**
	 * 登陆
	 */
	public void registerSipAccount()
	{
		if(the_sipengine_ == null)
			return;
		
		SharedPreferences sp = PreferenceManager
				.getDefaultSharedPreferences(this);
		boolean use_webrtc_mode = true;//sp.getBoolean("sip_account_use_webrtc_mode", true);
		//String phoneNumber = sp.getString("sip_account_username", "");
		//String password = sp.getString("sip_account_password", "");
		String display_name = sp.getString("sip_account_displayname", "");
		String auth_name = sp.getString("sip_account_auth_name", "");
		//String sip_server = sp.getString("sip_account_domain", "");
		String expire = "1800";//sp.getString("sip_account_expire", "600");
		SipTransportType trans_type  = SipTransportType.fromString("tls");
		
		if (!TextUtils.isEmpty(phoneNumber) && !TextUtils.isEmpty(password)
				&& !TextUtils.isEmpty(sip_server))
		{
			profile = the_sipengine_.GetSipProfileManager().selectSipProfile(
					"main_profile");
			
			
			if((!profile.username.equals(phoneNumber) ||
					profile.password.equals(password) ||
					profile.server.equals(sip_server) ||
					profile.domain.equals(sip_server)) && the_sipengine_.GetRegistrationManager().ProfileIsRegistered(profile))
			{
				the_sipengine_.GetRegistrationManager().MakeDeRegister(profile);
			}
			
			profile.username = phoneNumber;
			
			if(auth_name.length() > 0)
				profile.auth_name = auth_name;
			else
				profile.auth_name = phoneNumber;
			
			if(display_name.length() > 0)
				profile.displayname = display_name;
			
			profile.displayname = phoneNumber;
			profile.password = password;
			profile.domain = sip_server;
			profile.server = sip_server;
			profile.send_register = true;
			profile.webrtc_mode = true;
			profile.register_expire = Integer.parseInt(expire);
			profile.trans_type = trans_type;
			profile.Save();

			the_sipengine_.GetRegistrationManager().MakeRegister(profile);
		}
	}

	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		
		Debug.i(TAG, "phone service onStart");
		
		if(the_sipengine_!=null)
		{
			//if(ProfileIsRegistered())
			//	refreshRegistration();
			//else
			//	registerSipAccount();
		}
	}

	@Override
	public void onDestroy() {
		Debug.i(TAG, "PhoneService::onDestroy");
		super.onDestroy();
		if (the_sipengine_ != null)
			the_sipengine_.GetRegistrationManager().RefreshRegistration(profile);
		the_service_instance_ = null;
		if (mNetWorkBroadCast != null)
			unregisterReceiver(mNetWorkBroadCast);
		mTimer.cancel();
		mTimer = null;
		
		unregisterHeadsetReceiver();
	}

	private MediaPlayer waitMedia = null;

	private void startCallingSound(boolean with_spk) {
		if (waitMedia == null) { // 播放去电等待声音
			waitMedia = UIUtils.phoneWaitSound(this);
		}
		if (the_sipengine_ != null) {
			the_sipengine_.GetMediaEngine().GetVoiceEngine()
					.SetLoudspeakerStatus(with_spk);
		}
	}

	public void stopCallingSound() {
		if (waitMedia != null) {
			waitMedia.stop();
			waitMedia.release();
			waitMedia = null;
		}
	}

	public void playCallSound(boolean isRinging, boolean isShock) {
		if (mediaPlayer == null) {

			if (isRinging) {
				mediaPlayer = UIUtils.phoneSound(getApplicationContext());
				if (mediaPlayer != null) {
					if (mediaPlayer.isPlaying()) {
						mediaPlayer.stop();
						mediaPlayer.reset();
					}
					mediaPlayer.start();
				}
			}
			if (isShock) {
				vib = UIUtils.Vibrate(this, true);
			}
		}
	}

	private String caller;
	SettingSharedPreference share = SettingSharedPreference
			.getSharedPreferenceUtils();

	public void OnNewCall(Direction dir, String peer_caller,
			boolean is_video_call, String device_type) {
		Debug.e(TAG, " service================================  OnNewCall :" +peer_caller);
		//call serial
	
		
		if (isSystemCalling) {
			Debug.i(TAG, "OnNewCall isSystemCalling=" + isSystemCalling);
			PhoneService.instance().Hangup();
			return;
		}

		caller = peer_caller;
		
		boolean mainActivityIsRunning = false;
		
		if (dir.IntgerValue() == Direction.Outgoing.IntgerValue())
		{
			SerialService.instance().SerialCall(peer_caller);
			Debug.i(TAG, "新去电 " + peer_caller);			
			if(is_video_call)
			{	
				SipapCallPeer peer = new SipapCallPeer();
				peer.status = Contacts.INVITE_VIDEO_REQUEST;
				peer.peerip = peer_caller;
				if(mSipCaListener != null) {
				   mSipCaListener.onCallConnected(0, peer);
				}				
			}
		} else {
			Debug.i(TAG, "新来电 " + peer_caller +"=========================:" +device_type);
			SerialService.instance().sendSerCameraCommand();
			remote_device_type = device_type;
			SipapCallPeer peer = new SipapCallPeer();
			peer.status = Contacts.RECEIVE_VIDEO_REQUEST;
			peer.peerip = peer_caller;
			Debug.i(TAG, "mSipReListener!=null     "+(mSipReListener!=null));
			AcceptCall(false);
			//if(mSipReListener != null) {
			  // mSipReListener.onCallReceived(peer);
			//}
			
			if(mainActivityIsRunning)
			{
				Debug.i(TAG, "转到来电界面!");
				if (!is_video_call) {
					//MethodUtil.goToVoiceCallMode(VideoChatMainActivity.instance(), peer_caller, Contacts.PHONESTATE_INCOMMING);
				} else {
					//MethodUtil.goToVideoCallMode(VideoChatMainActivity.instance(), peer_caller, Contacts.RECEIVE_VIDEO_REQUEST);
				}
			} else {
				Debug.i(TAG, "创建来电界面!");				
			}		
		}		
	}

	public void OnCallConnected(Call call, boolean is_video_call) {
		Debug.e(TAG, "service========通话链接============================= ");

		if(call.GetDirection().IntgerValue() == Direction.Outgoing.IntgerValue())
		{
			SerialService.instance().sendOpenCameraCommand();;
		}
		
		// 开启通话时间计时
		/*TimeProcess.getInstance().startTime();
		// 设置回调
		TimeProcess.getInstance().setListener(new OnNotifactionListener() {
			@Override
			public void notificationTimeChange(String time) {
				showTalkingNotification(time);
			}

			@Override
			public void notificationTimeStop() {
				if (talKingNM != null) {
					talKingNM.cancel(TALKINGNOTIFICATION_ID);
				}
			}
		});*/

		// 停止来电声音
		stopCallingSound();

		/*if (VoiceCallActivity.instance() != null
				|| VideoScreenActivity.instance() != null) {
			sendMessage(Contacts.CALL_CONNECT);
		}*/

		if (mediaPlayer != null) {
			if (mediaPlayer.isPlaying()) {
				mediaPlayer.stop();
				mediaPlayer.release();
			}
			mediaPlayer = null;
		}

		if (vib != null) {
			vib.cancel();
			vib = null;
		}

		// 如果通话类型有变化则更新对应得activity
		//resetTalkingNotificationIntent(is_video_call);
		
		if (is_video_call)
		{
			// 如果是视频通话则设置免提
			SetLoudspeakerStatus(true);
			/*if (VoiceCallActivity.instance() != null)
			{ // 如果从语音更新到视频，则关闭语音界面
				VoiceCallActivity.instance().finish();
			}*/
		} else { // 如果不是视频通话则正常
			SetLoudspeakerStatus(true);
			//sendMessage(Contacts.CALL_MEDIA_CONNECTED);
		}
	}


	public void OnCallEnded() {
		Debug.i(TAG, "service  OnCallEnded() ");
		// 停止计时
		//TimeProcess.getInstance().stopTimer();

		// 停止来电时间
		stopCallingSound();
		
		/* 来电结束移除通知 */
		NotificationManager nm = (NotificationManager)PhoneService.this
				.getSystemService(Context.NOTIFICATION_SERVICE); // get
		if (nm != null) {
			nm.cancel(Contacts.NOTIFICATION_CALL_ID);
		}
		/*if (VoiceCallActivity.instance() == null
				&& VideoScreenActivity.instance() == null)
		{
			Debug.i(TAG, "呼叫结束");
			try {
				Thread.sleep(500);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}*/
		//sendMessage(Contacts.CALL_DISCONNECT);
        if(mSipCallDisconnectListener != null)
        	mSipCallDisconnectListener.onCallDisConnect();
        
		if (mediaPlayer != null) {
			if (mediaPlayer.isPlaying()) {
				mediaPlayer.stop();
				mediaPlayer.release();
			}
		}
		mediaPlayer = null;

		if (vib != null)
		{
			vib.cancel();
			vib = null;
		}
	}

	public void OnCallFailed(int status) {
		Debug.i(TAG, "service  OnCallFailed status＝" + "" + status);
		// 停止计时
		//TimeProcess.getInstance().stopTimer();
		stopCallingSound();
		
		String result = UIUtils.showCallReqStatus(status,
				getApplicationContext());
		
		//sendMessage(Contacts.CALL_FAILED, result);
		if(mSipCallDisconnectListener != null)
        	mSipCallDisconnectListener.onCallDisConnect();
		
		if (mediaPlayer != null && mediaPlayer.isPlaying()) {

			mediaPlayer.stop();
			mediaPlayer.release();
		}
		mediaPlayer = null;
		if (vib != null)
		{
			vib.cancel();
			vib = null;
		}
	}

	public void OnCallReport(CallReport cdr) {
		  {
			String peer_caller = cdr.From();
			String call_type = "audio";

			int type = Contacts.MSG_TYPE.CALL_AUDIO.ordinal();
			if (cdr.GetDirection() == Direction.Outgoing) {
				peer_caller = cdr.To();
			} else {
				peer_caller = cdr.From();
			}
			
			Debug.i(TAG, "OnCallReport isVideoCall:" + cdr.IsVideoCall());
			if (cdr.IsVideoCall()) {
				call_type = "video";
				type = Contacts.MSG_TYPE.CALL_VIDEO.ordinal();
			}
			
			DecimalFormat df = new DecimalFormat("#.0");
			String result = df.format(System.currentTimeMillis());
			String dir;
			String duration;
			String time;
			String status;
			if (cdr.RecordFile().length() > 0 ) {
				Debug.i("SipEngineTest",
						"[" + call_type + "]通话纪录: " + peer_caller + "\n状态 "
								+ cdr.GetCallReportStatus().toString() + "\n呼叫方向 "
								+ cdr.GetDirection().toString() + "\n呼叫时间 "
								+ cdr.GetStartTime() + "\n呼叫时长 "
								+ cdr.GetDuration() + "\n录音文件 "
								+ cdr.RecordFile());
				String[] date = UIUtils.devideData(cdr.GetStartTime());
				Debug.i(TAG, "OnCallReport = " + result);

				time = date[1];
				dir = cdr.GetDirection().toString();
				duration = "" + cdr.GetDuration();
				status = cdr.GetCallReportStatus().toString();
			} else {
				Debug.i("SipEngineTest",
						"[" + call_type + "]通话纪录: " + peer_caller + "\n状态 "
								+ cdr.GetCallReportStatus().toString() + "\n呼叫方向 "
								+ cdr.GetDirection().toString() + "\n呼叫时间 "
								+ cdr.GetStartTime() + "\n呼叫时长 "
								+ cdr.GetDuration());
				String[] date = UIUtils.devideData(cdr.GetStartTime());
				Debug.i(TAG, "OnCallReport  = " + result);
				time = date[1];
				dir = cdr.GetDirection().toString();
				duration = "" + cdr.GetDuration();
				status = cdr.GetCallReportStatus().toString();
			}
			String callType = cdr.IsVideoCall()? "video" : "audio";
			
			
			//BeeChatDataBase.getBeeChatDataBase().insertCallRecord(getContentResolver(),
				//	callLog);
			Debug.i(TAG, "OnNewCall report " + "peer_number " + peer_caller
					+ " isVideoCall=" + cdr.IsVideoCall());

			if ((!CallReportStatus.Answered.equals(cdr.GetCallReportStatus())
					|| !CallReportStatus.Cancel.equals(cdr.GetCallReportStatus())) 
					&& "0".equals(duration) && Direction.Incoming.equals(cdr.GetDirection())
					/*&& VideoChatMainActivity.instance() == null*/)
			{
				//UIUtils.showNotificationWhenMsg(this, peer_caller,
					//	getString(R.string.call_missed));
			}
			
			//if(VideoChatMainActivity.instance() != null)
			//{
				//VideoChatMainActivity.instance().ReloadCallReport();
			//}
		}

	}

	public void OnCallReceivedUpdateRequest(boolean has_video)
	{

		Debug.i(TAG, " service    OnCallReceivedUpdateRequest ");
		// 后台模式直接启动 视频接听 界面
		/*if (VideoScreenActivity.instance() == null) {
			Intent intent = new Intent(getBaseContext(),
					VideoScreenActivity.class);
			intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
			intent.putExtra(Contacts.PHONESTATE,
					Contacts.RECEIVE_VIDEO_REQUEST);
			intent.putExtra(Contacts.ACTION_FROM_SERVICE,
					Contacts.ACTION_FROM_PHONE_SERVICE);
			intent.putExtra(Contacts.PHONNUMBER, caller);
			intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			startActivity(intent);
		}
		
		if (VideoScreenActivity.instance() == null) {
			MethodUtil.goToVideoCallMode(this, caller,
					Contacts.RECEIVE_VIDEO_REQUEST);
		}*/
	}
	
	/*
	 * public void OnTextMessageDelivered(String message_id) {
	 * if(the_ui_event_linstener_!=null){
	 * the_ui_event_linstener_.OnTextMessageDelivered(message_id); } // else{ //
	 * 更新消息送达状态 // String str = convertMsgid(message_id); //
	 * MsgChatManager.getInstance
	 * ().updateMessageSendStatus(getContentResolver(), str,
	 * Constants.MSG_ARRIVED); // } }
	 */
	public String convertMsgid(String msgId) {
		return msgId.replaceAll("/", "-");
	}

	class NetWorkBroadCast extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			
			Debug.d(TAG, "网络状态改变");

			// 获得网络连接服务
			ConnectivityManager connManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);

			NetworkInfo mNetworkInfo = connManager.getActiveNetworkInfo();
			try {
				if (mNetworkInfo != null && mNetworkInfo.isAvailable()) {
					Debug.d(TAG, "网络状态[UP]!");
					
					if (the_sipengine_ != null)
					{
						the_sipengine_.GetRegistrationManager()
								.SetNetworkReachable(true);
						
						registerSipAccount();
					}

				} else {
					Debug.e(TAG, "网络状态[DOWN]!");
					if (the_sipengine_ != null)
						the_sipengine_.GetRegistrationManager()
								.SetNetworkReachable(false);
				}
			} catch (Exception e) {
				e.printStackTrace();
				Debug.e(TAG, "网络状态[DOWN]!");
				if (the_sipengine_ != null)
					the_sipengine_.GetRegistrationManager()
							.SetNetworkReachable(false);
			}
		}
	}

	NotificationManager talKingNM;
	RemoteViews remoteViews;
	PendingIntent contentIntent;
	Notification talkingNft;

	public static final int TALKINGNOTIFICATION_ID = 30;

	/**
	 * 初始化通话时间通知栏
	 * 
	 * @param isVideo
	 * @param callNumber
	 * @param direction
	 * 
	 */
	public void initTalkingNotification(boolean isVideo, String phoneNumber,
			int direction) {
		/*String service = Context.NOTIFICATION_SERVICE;
		talKingNM = (NotificationManager) this.getSystemService(service); // get
		int icon = R.drawable.notification_icon;
		long when = System.currentTimeMillis();
		talkingNft = new Notification(icon, getString(R.string.incall), when);
		talkingNft.flags = Notification.FLAG_ONGOING_EVENT;
		Intent intent = null;

		// 根据电话类型拼装不同的intent
		if (isVideo) {
			intent = new Intent(this, VideoScreenActivity.class);
			intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
		} else { // 需要跳转到语音
			intent = new Intent(this, VoiceCallActivity.class);
			intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
		}

		contentIntent = PendingIntent.getActivity(this, 0, intent,
				PendingIntent.FLAG_CANCEL_CURRENT);
		remoteViews = new RemoteViews(getPackageName(), R.layout.layout_talking);
		// 去数据库中查找对应的好友
		String code = SettingSharedPreference.getSharedPreferenceUtils()
				.getDate(this, Contacts.SHARE_AREA_CODE,
						Contacts.COUNTRY_CODE);
		String searchNumber = ContactsUtil.convertPrefix(phoneNumber, code);
		Contact contact = BeeChatDataBase.getBeeChatDataBase()
				.queryFriendByNumber(getContentResolver(), searchNumber);
		if (contact != null && !TextUtils.isEmpty(contact.name)) {
			phoneNumber = contact.name;
		}
		remoteViews.setTextViewText(R.id.tv_name, phoneNumber);
		remoteViews.setTextViewText(R.id.tv_time, getString(R.string.incall)
				+ " (" + 0 + ")");
		UIUtils.getHourAndMin(this);
		remoteViews.setTextViewText(R.id.tv_systime, "" + new Date().getTime());
		remoteViews.setImageViewResource(R.id.iv_pic, R.drawable.ic_bc);
		talkingNft.contentView = remoteViews;
		talkingNft.contentIntent = contentIntent;*/
	}

	/**
	 * 重置 intent得指向
	 * 
	 * @param isVideo
	 */
	public void resetTalkingNotificationIntent(boolean isVideo) {
		Intent intent;
		// 如果是视频通话得发送视频通话得Intent
		if (isVideo) {
			//intent = new Intent(this, VideoScreenActivity.class);
			//intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
		} else {
			//intent = new Intent(this, VoiceCallActivity.class);
			//intent.putExtra(Contacts.PHONEFRONT, true);
		}
		if (talkingNft != null && contentIntent != null) {

			//contentIntent = PendingIntent.getActivity(this, 0, intent,
				//	PendingIntent.FLAG_CANCEL_CURRENT);
		}
	}

	/**
	 * 更新通知栏时间
	 * 
	 * @param context
	 * @param time
	 * @param date
	 */
	public void showTalkingNotification(String time) {
		/*remoteViews.setTextViewText(R.id.tv_time, getString(R.string.incall) + " (" + time + ")");
		// 获取格式化后的时间
		String t = UIUtils.getHourAndMin(this);
		remoteViews.setTextViewText(R.id.tv_systime, t);
		talkingNft.contentView = remoteViews;
		talkingNft.contentIntent = contentIntent;
		talKingNM.notify(TALKINGNOTIFICATION_ID, talkingNft);*/// 发送通知
	}

	@Override
	public void OnCallStateChange(long callPtr, int state_code) {
		Call call = new CallImpl(callPtr);
		CallState state = CallState.fromInt(state_code);
		Debug.d(TAG, "OnCallStateChange (call = " + call.GetUniqueId() + ", caller = " + call.GetCallerId()
				+ ", state = " + state.toString() + ")");

		if (state.IntgerValue() == CallState.NewCall.IntgerValue())
		{
			if(current_call != null)
			{
				call.Reject(486, "Busy Here");
				return;
			}
			
			if (call.GetDirection().IntgerValue() == Direction.Outgoing
					.IntgerValue()) {
				startCallingSound(call.GetSupportVideo());
			} else {
				the_sipengine_.GetMediaEngine().GetVoiceEngine()
						.SetLoudspeakerStatus(true);
				boolean set_beechat_ringing = share.getDate(this,
						Contacts.SET_BEECHAT_RINGING_KEY, true);
				boolean set_beechat_shock = share.getDate(this,
						Contacts.SET_BEECHAT_SHOCK_KEY, true);
			
				if(isTvBoxMode() == false)
					playCallSound(set_beechat_ringing, set_beechat_shock);
			}
		}

		{
			/* 处理新呼叫 */
			if (state.IntgerValue() == CallState.NewCall.IntgerValue()) {
				current_call = call;
				
				if(call.GetSupportVideo())
				{
					call.GetMediaStream().GetVideoStream().RegisterVideoStreamObserver(this);
				}
				
				OnNewCall(call.GetDirection(), call.GetCallerId(),
						call.GetSupportVideo(), call.GetDeviceType());
			} else if (state.IntgerValue() == CallState.Failed.IntgerValue()
					|| state.IntgerValue() == CallState.Rejected.IntgerValue()
					|| state.IntgerValue() == CallState.Cancel.IntgerValue()) {
				if(call.GetUniqueId().equals(current_call.GetUniqueId()))
				{
					current_call = null;
					OnCallFailed(call.GetErrorCode());
					OnCallReport(call.GetCallReport());
				}
			} else if (state.IntgerValue() == CallState.EarlyMedia
					.IntgerValue()) {
				OnCallRinging();
			} else if (state.IntgerValue() == CallState.Ringing.IntgerValue()) {
				OnCallProcessing();
			} else if (state.IntgerValue() == CallState.Answered.IntgerValue()) {
				OnCallConnected(call, call.GetSupportVideo());
			} else if (state.IntgerValue() == CallState.Hangup.IntgerValue()) {
				if(call.GetUniqueId().equals(current_call.GetUniqueId()))
				{
					current_call = null;
					OnCallEnded();
					OnCallReport(call.GetCallReport());
				}
			} else if (state.IntgerValue() == CallState.Pausing.IntgerValue()) {

			} else if (state.IntgerValue() == CallState.Resumed.IntgerValue()) {
				OnCallPaused();
			} else if (state.IntgerValue() == CallState.Resuming.IntgerValue()) {
				OnCallResuming();
			} else if (state.IntgerValue() == CallState.Resumed.IntgerValue()) {

			} else if (state.IntgerValue() == CallState.Updating.IntgerValue()) {

			} else if (state.IntgerValue() == CallState.Updated.IntgerValue()) {

			}
		}
	}

	@Override
	public void OnDtmf(long callPtr, String tone) {
		new CallImpl(callPtr);
		System.out.println("===============OnDtmf=================:" +tone);
		if(tone.contains("*"))
			SerialService.instance().sendUnlockCommand();
	}

	@Override
	public void OnRegistrationProgress(SipProfile profile) {
		Debug.d(TAG, "OnRegistrationProgress username = " + profile.username);
		//VideoChatMainActivity main_activity = VideoChatMainActivity.instance();
		/*if(main_activity!=null)
		{
			main_activity.SetRegistrationState(RegistrationState.Progress,RegistrationErrorCode.None);
		}*/
		reg_error_code = RegistrationErrorCode.None;
		reg_state = RegistrationState.Progress;
	}

	@Override
	public void OnRegistrationSuccess(SipProfile profile) {
		Debug.d(TAG, "OnRegisterationSucess username = " + profile.username);
		//VideoChatMainActivity main_activity = VideoChatMainActivity.instance();
		if(mSipRiListener != null)
		{
			mSipRiListener.onRegister(1);
		}
		reg_error_code = RegistrationErrorCode.None;
		reg_state = RegistrationState.Sucess;
	}

	@Override
	public void OnRegistrationCleared(SipProfile profile) {
		Debug.d(TAG, "OnRegistrationCleared username = " + profile.username);
		if(mSipRiListener != null)
		{
			mSipRiListener.onRegister(0);
		}
		reg_error_code = RegistrationErrorCode.None;
		reg_state = RegistrationState.Cleared;
	}

	@Override
	public void OnRegisterationFailed(SipProfile profile, int code,
			String reason)
	{
		Debug.w(TAG, "OnRegisterationFailed username = " + profile.username
				+ ", code = " + code + ", reason = " + reason);
		reg_error_code = new RegistrationErrorCode(reason,code);
		reg_state = RegistrationState.Failed;
		
		if(mSipRiListener != null)
		{
			mSipRiListener.onRegister(0);
		}
		
	}
	
	@SuppressLint("HandlerLeak")
	private Handler handler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case STOPHOLDSOUND: //
				if (audioManager != null)
					audioManager.setMode(AudioManager.MODE_NORMAL);
				break;
			}
		}
	};
	
	private final int STOPHOLDSOUND = 89;
	private AudioManager audioManager = null;
	public void playHoldSound() {
		try {
			if (audioManager == null) {
				audioManager = (AudioManager) this
						.getSystemService(Context.AUDIO_SERVICE);
			}
			audioManager.setMode(AudioManager.MODE_IN_CALL);
			UIUtils.playHoldSound(this);
			Message msg = new Message();
			msg.what = STOPHOLDSOUND;
			handler.sendMessageDelayed(msg, 2000);
		} catch (Exception e) {
			e.printStackTrace();
			audioManager.setMode(AudioManager.MODE_NORMAL);
		}
	}
	
	public void OnCallProcessing() {
		Debug.i(TAG, "正在接续");
		//sendMessage(Contacts.CALL_PROCESSING);
	}

	public void OnCallRinging() {
		Debug.i(TAG, "正在振铃");
		//sendMessage(Contacts.CALL_RINING);
		stopCallingSound();
	}
	
	public void OnCallPausedByRemote() {
		Debug.i(TAG, "对方 呼叫保持");
		//sendMessage(Contacts.CALL_HOLDED);
		playHoldSound();
	}
	
	public void OnCallResumingByRemote()
	{
		Debug.i(TAG, "对方 呼叫恢复");
		//sendMessage(Contacts.CALL_RESUMED);
	}

	public void OnCallUpdated(boolean has_video) {
		Debug.i(TAG, "CallUpdated");
	}
	
	public void OnCallPaused() {
		Debug.i(TAG, "本方  呼叫保持");
		//sendMessage(Contacts.CALL_HOLDDING);
	}

	public void OnCallResume() {
		Debug.i(TAG, "通话恢复");
		//sendMessage(Contacts.CALL_RESUME);
	}
	
	public void OnCallResuming() {
		Debug.i(TAG, "service  OnCallResuming ");
		//sendMessage(Contacts.CALL_RESUME);
	}

	/**
	 * 判断是否有系统来电
	 */
	public static boolean isSystemCalling = false;

	/**
	 * 媒体流协商成功,启动视频画面
	 */
	@Override
	public void OnMediaStreamReady(long callPtr, int stream_type) {
		final Call call = new CallImpl(callPtr);
		final StreamType type = StreamType.fromInt(stream_type);
		Debug.e(TAG, "service=========OnMediaStreamReady(call = " + call.GetUniqueId() + ", type = " + type.toString() + ")");

		if (type.IntgerValue() == StreamType.VideoStream.IntgerValue() && call.GetSupportVideo()) {
			mHandler.postDelayed(new Runnable() {
				@Override
				public void run() {
					//add by xuweihong
					 mSipAsListener.onAddStream(call.GetDirection());
				}
			},500);
		}
	}

	VideoFrameInfo frame_info = new VideoFrameInfo();
	
	public VideoFrameInfo GetVideoFrameInfo()
	{
		return frame_info;
	}

	@Override
	public void OnIncomingRate(int video_channel, int framerate, int bitrate) {
		Debug.i(TAG, "PhoneService::OnIncomingRate(framerate="+ framerate +",bitrate="+(bitrate/1024) +")"); 
		frame_info.rx_bitrate = bitrate;
		frame_info.rx_framerate = framerate;
	}

	@Override
	public void OnOutgoingRate(int video_channel, int framerate, int bitrate) {
		Debug.i(TAG, "PhoneService::OnOutgoingRate(framerate="+ framerate +",bitrate="+(bitrate/1024) +")"); 
		frame_info.tx_bitrate = bitrate;
		frame_info.tx_framerate = framerate;
	}

	@Override
	public void OnVideoFrameSizeChanged(int video_channel, int width, int height) {
		Debug.i(TAG, "PhoneService::OnVideoFrameSizeChanged(video_channel="+ video_channel +",width="+width +",height=" + height +")"); 
		frame_info.rx_video_width = width;
		frame_info.rx_video_height = height;
	}
	
	//add by xuweihong
	public void Register(String user_id, String password, String server)
	{
		phoneNumber = user_id;
		this.password = password;
		sip_server = server;
		this.registerSipAccount();
	}
	
	public int GetRegistered() {
		profile = the_sipengine_.GetSipProfileManager().selectSipProfile(
				"main_profile");
		
		if(the_sipengine_.GetRegistrationManager().ProfileIsRegistered(profile))
			return 1;
		else return 0;
	}	
	
	public void UnRegister() {
		profile = the_sipengine_.GetSipProfileManager().selectSipProfile(
				"main_profile");
		
		if(the_sipengine_.GetRegistrationManager().ProfileIsRegistered(profile))
			the_sipengine_.GetRegistrationManager().MakeDeRegister(profile);
	}
	
	public void Call(String peer, String device_type) {
		MakeCall(peer, true, device_type);
	}
	
	public int GetCall()
	{
	   if (current_call != null || profile == null) {
			/* busy */
			return 1;
		} else return 0;
	}
	//end by xuweihong
}
